using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using YTS.Tools;

namespace Test.ConsoleProgram.Algorithm.Work
{
    [TestDescription("工作逻辑: JSON数据格式自定义转化")]
    public class Test_JsonCustomConvert : AbsBaseTestItem
    {
        public override void OnTest()
        {
            var field = new Field()
            {
                Description = "测试",
                Value = 1,
                UserIds = new int?[] {
                    4,5,6,7,null,-2, -4,
                },
            };
            var str = "{\"Description\":\"测试\",\"Value\":1,\"UserIds\":\"4,5,6,7,-2,-4\"}";
            Assert.TestExe(JsonConvert.SerializeObject, field, str);
            Assert.TestExe(JsonConvert.DeserializeObject<Field>, str, field);
        }


        private class Field
        {
            public string Description { get; set; }
            public object Value { get; set; }

            [JsonConverter(typeof(JsonCustomIListInt32NullToStringConvert), ",")]
            public IList<int?> UserIds { get; set; }
        }

        public abstract class AbsJsonCustomIListToStringConvert<T> : CustomCreationConverter<IList<T>>
        {
            public readonly string separator;
            public AbsJsonCustomIListToStringConvert()
            {
                separator = ",";
            }
            public AbsJsonCustomIListToStringConvert(string separator)
            {
                this.separator = separator;
            }

            /// <summary>
            /// 转换值方法
            /// </summary>
            public abstract T ConvertItemFunc(string str);
            public abstract string ConvertItemFunc(T value);

            public override IList<T> Create(Type objectType)
            {
                return new List<T>() { };
            }

            public override bool CanWrite { get { return true; } }

            public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
            {
                object readValue = reader.Value;
                if (readValue == null)
                {
                    return new List<T>() { };
                }
                var str = readValue.ToString();
                return str.Split(separator.ToCharArray())
                    .Select(b => ConvertItemFunc(b))
                    .Where(b => b != null)
                    .ToList();
            }

            public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
            {
                if (value == null)
                {
                    writer.WriteNull();
                    return;
                }
                if (value is IList<T> list)
                {
                    var strlist = list
                        .Select(b => ConvertItemFunc(b))
                        .Where(b => b != null)
                        .ToList();
                    string strResult = string.Join(separator, strlist);
                    writer.WriteValue(strResult);
                    return;
                }
                writer.WriteNull();
            }
        }

        public class JsonCustomIListInt32NullToStringConvert : AbsJsonCustomIListToStringConvert<int?>
        {
            public JsonCustomIListInt32NullToStringConvert() : base() { }
            public JsonCustomIListInt32NullToStringConvert(string separator) : base(separator) { }

            public override int? ConvertItemFunc(string str)
            {
                var value = ConvertTool.ToInt(str, int.MinValue);
                return value == int.MinValue ? null : (int?)value;
            }

            public override string ConvertItemFunc(int? value)
            {
                return value == null ? null : value.ToString();
            }
        }
    }
}
